home *** CD-ROM | disk | FTP | other *** search
- /* demo.c */
-
-
-
- /* A small demo program for the Rxil library.
- *
- * This must be run from the CLI only. This is due to the diagnostic
- * info that is sent to the CLI.
- *
- * This program implments a fairly full-featured ARexx port.
- * The demo program itself is more along the lines of a "hack" and
- * was not written with robustness in mind (especially the child macro
- * launching stuff).
- * It does show how few the lines of code needed are.
- */
-
-
-
- /* Copyright © 1989 by Donald T. Meyer, Stormgate Software
- * All Rights Reserved
- *
- * This source code may be compiled and used in any software
- * product.
- * No portion of this source code is to be re-distributed or
- * sold for profit.
- *
- * Donald T. Meyer
- * Stormgate Software
- * P.O. Box 383
- * St. Peters, MO 63376
- *
- * BIX: donmeyer (usually daily)
- * GEnie: D.MEYER (weekly)
- * PLINK: Stormgate (weekly)
- */
-
-
-
- /* The Commands this program understands from ARexx:
- *
- * STATUS <l|b|x|y|z>
- * A do-nothing command which returns various strings and result
- * codes.
- *
- * DUMP [e|c|s]
- * Display some things about the ARexx environment that this
- * program has established.
- *
- * LOCK
- * Engage this program in an exclusive conversation.
- * Returns the name of the secret port.
- *
- * UNLOCK
- * Releases the lock.
- *
- * LCMD
- * Allows the launching of an ARexx program as a "command".
- *
- * LFUNC
- * Allows the launching of an ARexx program as a "function".
- *
- * PTEST
- * Returns a dummy string. Works only from a "child" ARexx
- * program or from an ARexx program which has acquired a lock.
- *
- * QUIT
- * Causes the program to terminate. This is the only way to
- * exit!
- *
- *
- * These descriptions are terse, I know. Looking at the code here
- * is the best way to get a feel for just what is happening.
- * To play with this, run it, and then run an ARexx program whose
- * host address is set to "MYREXX_TEST_#1".
- * Then issue some commands! Note that most things require that the
- * results flag be set via an ARexx "options results" statement.
- */
-
-
-
- #include "rxil.h"
-
- #include <graphics/gfxbase.h>
- #include <libraries/dos.h>
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
-
- #ifdef LATTICE
- #include <proto/intuition.h>
- #endif
-
-
-
- /*--------------------------------------------------------------------*/
-
- void openlibrarys( void );
- void closelibrarys( void );
- void cleanup( void );
- void bailout( char *message, int rc );
-
- void eventloop( void );
-
-
-
- void cmd_status( struct RexxMsg *rexxmsg );
- void cmd_quit( struct RexxMsg *rexxmsg );
- void cmd_launch_cmd( struct RexxMsg *rexxmsg );
- void cmd_launch_func( struct RexxMsg *rexxmsg );
- void cmd_ptest( struct RexxMsg *rexxmsg );
- void cmd_dump( struct RexxMsg *rexxmsg );
-
-
-
- /*--------------------------------------------------------------------*/
-
- struct IntuitionBase *IntuitionBase = NULL;
- struct GfxBase *GfxBase = NULL;
-
-
- BOOL finished = FALSE;
-
-
-
- /************************************
- * *
- * Defined for Rexx Interface *
- * *
- ************************************/
-
- struct RxilDef *global_rdef = NULL;
-
-
- struct RxilFunction rexx_cmd_table[] = {
- { "lock", &RxilCmdLock, 0, 0, FALSE, RXIL_PUBLIC },
- { "unlock", &RxilCmdUnlock, 0, 0, FALSE, RXIL_SECRET },
-
- { "status", &cmd_status, 1, 1, FALSE, RXIL_PUBLIC },
- { "quit", &cmd_quit, 0, 0, FALSE, RXIL_PUBLIC },
- { "dump", &cmd_dump, 0, 1, FALSE, RXIL_PUBLIC },
- { "lcmd", &cmd_launch_cmd, 0, 0, FALSE, RXIL_PUBLIC },
- { "lfunc", &cmd_launch_func, 0, 0, FALSE, RXIL_PUBLIC },
- { "ptest", &cmd_ptest, 0, 0, FALSE, RXIL_SECRET },
-
- /* Mark end-of-table */
- { NULL, NULL, 0, 0, FALSE, 0 }
- };
-
-
- /********************************************************************/
-
-
- struct RxilInvocation *rxi_func;
- struct RxilInvocation *rxi_cmd;
- /* For general purpose testing use. These would not be
- * needed as other than local, temporary variables if we were
- * allocating and de-allocating RxilInvocation structures on
- * the fly (since the Rxil library tracks all RxilInvocation
- * structures allocated).
- */
-
-
- struct RxilInvocation *rxi_startup;
- /* This one is for the startup macro. We want to retain it's pointer
- * even after it is launched so that we can "recognize" it when
- * it terminates and handle it differently.
- */
-
-
- /*--------------------------------------------------------------------*/
-
-
- void main( int argc, char *argv[] )
- {
- openlibrarys();
-
-
- /* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
- * This will open the rexx library, and the desired ports.
- * If all we want to do is receive commands, we probably
- * would not open the secret port, although we might.
- */
- global_rdef = RxilInit( RXIL_PUBLIC | RXIL_SECRET, "MYREXX_TEST" );
- if( global_rdef == NULL )
- {
- bailout( "Unable to init rexx", 0 );
- }
-
-
- /* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
- * Init the members in the RxilDef structure which customize
- * the way things work.
- */
-
- /* global_rdef->Flags = RXIL_NO_REQ | RXIL_NO_ABORT; */
- /* Set flags here to control various characteristics of the
- * library routines.
- * The default in this demo is to not set any flags, which
- * typicaly turn _off_ features.
- */
-
- global_rdef->Console = "CON:10/10/400/150/RexxCon";
- /* All commands or functions launched by this program will open
- * a console window of this specification. Set this to NULL to
- * default to no window.
- */
-
- global_rdef->Extension = "rexx";
- /* this normally would be an application
- * specific macro filename extension.
- */
-
- global_rdef->HostPort = "REXX";
- /* If this is AREXX, launches will default
- * to async (as opposed to synchronous).
- */
-
- global_rdef->CommandTable = &rexx_cmd_table[0];
-
-
-
-
-
- /* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
- * Pre-allocate some invocation structures. These could
- * also be allocated and de-allocated on-the-fly if desired.
- * One possible philosophy would be to allocate one structure
- * for each possible macro command. This would speed macro
- * invocations by a slight amount.
- */
- rxi_cmd = RxilCreateRxi( NULL, RXCOMM );
- if( rxi_cmd == NULL )
- {
- bailout( "Unable to allocate command_rxi", RETURN_FAIL );
- }
-
- rxi_func = RxilCreateRxi( NULL, RXFUNC );
- if( rxi_func == NULL )
- {
- bailout( "Unable to allocate function_rxi", RETURN_FAIL );
- }
-
-
-
- /* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
- * This is an example of running a "startup" macro each time the
- * program is invoked. The RxilInvocation will be allocated and
- * then freed when it returns.
- */
- rxi_startup = RxilCreateRxi( "startup.rxil", RXCOMM );
- if( rxi_startup == NULL )
- {
- /* Just because the startup macro did not work, you would
- * probably not normally give up.
- */
- printf( "** Unable to allocate startup rxi **\n" );
- }
- else
- {
- /* We want our own console spec, not the default. In some
- * (most?) real applications a console would probably not be
- * opened. We do it here for illustration purposes.
- */
- rxi_startup->Console = "CON:0/80/620/100/Demo Startup Macro";
-
- if( RxilLaunch( rxi_startup ) != 0 )
- {
- /* Informative message only */
- printf( "** Unable to launch the startup macro **\n" );
- }
- }
-
- eventloop();
-
- cleanup();
- }
-
-
-
- /*-----------------------------------------------------------------*/
-
-
- void eventloop( void )
- {
- struct RxilInvocation *rxi;
- ULONG flags;
-
-
- while( !finished )
- {
- /* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
- * Note that we include the rexx port signal bit(s) in the wait().
- */
- flags = Wait( RXIL_WAITFLAG );
-
-
- /* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
- * Now do the ARexx port stuff.
- */
- if( FlagIsSet( flags, RXIL_WAITFLAG ) )
- {
- RxilCheckPort();
- }
-
-
- /* Some info for debugging purposes... */
-
- printf( "---Event---\n" );
- printf( "rxi_cmd state: %d\n", (int)rxi_cmd->State );
- printf( "rxi_func state: %d\n", (int)rxi_func->State );
-
-
- /* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
- * Get any ARexx invocation returns which may be back.
- * This code would not be present on a minimal implementation
- * which does not launch macros, just responds to simple
- * commands.
- */
- while( ( rxi = RxilGetReturn() ) != NULL )
- {
- if( rxi->Type == RXCOMM )
- {
- printf( "Command Invocation completed\n" );
- }
- else
- {
- printf( "Function Invocation completed\n" );
- }
-
- if( rxi == rxi_startup )
- {
- /* This is our startup macro terminating. We handle
- * this differently since we don't want to display
- * an error if not found (which the standard routine
- * RxilHandleReturn would do). And we also want to
- * de-allocate the RxilInvocation structure.
- */
-
- /* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+
- * Deallocate things, close console windows, etc.
- * Then free the structure.
- */
- if( ( rxi->RexxMsg->rm_Result1 != RC_WARN ) ||
- ( rxi->RexxMsg->rm_Result2 != ERR10_001 ) )
- {
- /* The error is not just "program not found".
- * This is a true error, tell the user.
- */
- RxilHandleReturn( rxi );
- }
-
- RxilCleanupReturn( rxi );
- RxilDeleteRxi( rxi );
- rxi_startup = NULL; /* To be tidy... */
- }
- else
- {
- /* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+
- * Tell user about error returns, etc.
- * This can either be replaced by client code to handle
- * returns in a specific way, or not done at all (not very
- * friendly) and nothing will break...
- */
- RxilHandleReturn( rxi );
-
- /* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+
- * Deallocate things, close console windows, etc.
- */
- RxilCleanupReturn( rxi );
- }
- }
- }
- }
-
-
-
- void cmd_status( struct RexxMsg *rexxmsg )
- {
- printf( "Cmd status\n" );
- printf( "The FromRexx variable is %d\n", RXIL_FROM_REXX );
-
- switch( *RXIL_ARGV(1) )
- {
- case 'L':
- case 'l':
- RxilSetResult( rexxmsg, "Hi there!" );
- break;
-
- case 'B':
- case 'b':
- RxilSetResult( rexxmsg, "I'm NOT Fine!" );
- break;
-
- case 'X':
- case 'x':
- rexxmsg->rm_Result1 = 20;
- break;
-
- case 'Y':
- case 'y':
- rexxmsg->rm_Result1 = 100;
- break;
-
- case 'Z':
- case 'z':
- rexxmsg->rm_Result1 = 200;
- break;
-
- default:
- rexxmsg->rm_Result1 = RXERR_INVALID_ARG;
- }
- }
-
-
-
- /* This will only succeed if the command comes in at the private port.
- */
-
- void cmd_ptest( struct RexxMsg *rexxmsg )
- {
- printf( "Cmd privilege test\n" );
-
- RxilSetResult( rexxmsg, "You are privileged indeed!" );
- }
-
-
-
- /* Cause the demo program to exit. */
-
- void cmd_quit( struct RexxMsg *rexxmsg )
- {
- printf( "Cmd quit\n" );
-
- finished = TRUE;
- }
-
-
-
- void cmd_dump( struct RexxMsg *rexxmsg )
- {
- ULONG flags = 0;
-
-
- if( RXIL_ARGC > 1 )
- {
- if( strnicmp( RXIL_ARGV(1), "ENVIRONMENT",
- strlen(RXIL_ARGV(1)) ) == 0 )
- {
- flags = RXIL_DUMP_ENV;
- }
-
- if( strnicmp( RXIL_ARGV(1), "STATE",
- strlen(RXIL_ARGV(1)) ) == 0 )
- {
- flags = RXIL_DUMP_STATE;
- }
-
- if( strnicmp( RXIL_ARGV(1), "COMMANDS",
- strlen(RXIL_ARGV(1)) ) == 0 )
- {
- flags = RXIL_DUMP_CMDS;
- }
- }
- else
- {
- flags = RXIL_DUMP_ENV | RXIL_DUMP_CMDS | RXIL_DUMP_STATE;
- }
-
- if( flags == 0 )
- {
- /* The keyword was not valid */
- rexxmsg->rm_Result1 = RXERR_INVALID_ARG;
- return;
- }
-
- RxilDumpRdef( global_rdef, flags );
- }
-
-
-
- void cmd_launch_cmd( struct RexxMsg *rexxmsg )
- {
- static char buf[100];
- LONG rc;
-
-
- printf( "Cmd launch command:" );
- gets( buf );
-
- rxi_cmd->Name = buf;
- rc = RxilLaunch( rxi_cmd );
- printf( "Launch returned %d\n", rc );
- }
-
-
-
- static char buf[16][100];
-
-
- void cmd_launch_func( struct RexxMsg *rexxmsg )
- {
- LONG rc;
- int i;
-
-
- printf( "Cmd launch function:" );
- gets( &buf[0][0] );
-
- for( i=1; i<16; i++ )
- {
- printf( "Enter arg %d: ", i );
- gets( &buf[i][0] );
- if( strlen(&buf[i][0]) > 0 )
- {
- rxi_func->FuncArg[i] = &buf[i][0];
- }
- else
- {
- rxi_func->FuncArg[i] = NULL;
- break;
- }
- }
-
- rxi_func->Name = &buf[0][0];
-
- rc = RxilLaunch( rxi_func );
-
- printf( "Launch returned %d\n", rc );
- }
-
-
-
- /*-----------------------------------------------------------------*/
-
-
-
-
- void openlibrarys( void )
- {
- /* Intuition */
- if( ! ( IntuitionBase = (struct IntuitionBase *)
- OpenLibrary("intuition.library", 33 ) ) )
- {
- bailout( "Unable to open the Intuition Library", RETURN_FAIL );
- }
-
- /* Graphics */
- if( ! ( GfxBase = (struct GfxBase *)
- OpenLibrary("graphics.library", 33 ) ) )
- {
- bailout("Unable to open the Graphics Library", RETURN_FAIL );
- }
- }
-
-
-
- void closelibrarys( void )
- {
- if( IntuitionBase ) CloseLibrary( (struct Library *)IntuitionBase );
- if( GfxBase ) CloseLibrary( (struct Library *)GfxBase );
- }
-
-
-
- void cleanup( void )
- {
- /* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
- * This will handle ALL the cleanup details. If we wished to make
- * sure that there were no macro program invocations running before
- * we call this routine (and it waits, which may distress the user)
- * we should test our ability to terminate by calling RxilPending().
- */
- RxilCleanup( global_rdef );
- global_rdef = NULL;
-
- closelibrarys();
- }
-
-
-
- void bailout( char *message, int rc )
- {
- printf( "%s/n", message );
- cleanup();
- exit( rc );
- }
-
-